package com.xinqi.service.impl;

import com.xinqi.service.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author xin麒
 * @date 2023/8/10 20:11
 */
@Slf4j
@Service
@EnableAsync
public class HelloServiceImpl implements HelloService {

    @Resource
    ThreadPoolTaskExecutor xinTaskExecutor;

    /*1、@Resource是JDK原生的注解，@Autowired是Spring2.5 引入的注解
    2、@Resource有两个属性name和type。Spring将@Resource注解的name属性解析为bean的名字，而type属性则解析为bean的类型。所以如果使用name属性，则使用byName的自动注入策略，而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性，这时将通过反射机制使用byName自动注入策略。
    @Autowired只根据type进行注入，不会去匹配name。如果涉及到type无法辨别注入对象时，那需要依赖@Qualifier或@Primary注解一起来修饰。
    链接：https://juejin.cn/post/7022507865701089317
    *

    如果是使用Autowired，那应该也是可以的，可以尝试下//会去匹配 @Bean("xinTaskExecutor") 这个线程池
        @Autowired
        ThreadPoolTaskExecutor xinTaskExecutor;
    * */
    @Override
    public Object processForCount(Long count) {
        xinTaskExecutor.execute(() -> {
            try {
                Thread.sleep(10 * 1000);
                log.debug("this 1 task");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        try {
            Thread.sleep(70 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        xinTaskExecutor.execute(() -> {
            try {
                Thread.sleep(1000);
                log.debug("this 2 task");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        log.debug("this 3 task");

        return "nice";
    }

    //TODO processForCount2和3的到底那种捕获异常的方式才是正确呢？实际上也就是抛出的异常怎么处理呢？
    //这里应该是着分析吧：
    //分2种情况来讨论：
    //1、execute内部的执行能让产生了异常，例如int n = 1 / 0;
// 2、线程数量已达最大线程数量，队列已满，执行拒绝策略为AbortPolicy
    //应该就这两个情况了吧，不知道有没有遗漏其他情况
    @Override
    public Object processForCount2(Long count) {
        for (int i = 0; i < 50; i++) {
            int index = i;
            xinTaskExecutor.execute(() -> {
                try {
                    Thread.sleep(1000 * 90);
                    log.debug(String.valueOf(index) + "hahaha");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        xinTaskExecutor.execute(() -> {
            try {
                Thread.sleep(1000 * 90);
                log.debug(String.valueOf(50));//第50个
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        return "nice";
    }

    @Override
    public Object processForCount3(Long count) {
        for (int i = 0; i < 50; i++) {
            int index = i;
            try {
                xinTaskExecutor.execute(() -> {
                    try {
                        Thread.sleep(1000 * 90);
                        log.debug(String.valueOf(index));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            xinTaskExecutor.execute(() -> {
                try {
                    Thread.sleep(1000 * 90);
                    log.debug(String.valueOf(50));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }


        return "nice";
    }

    @Resource
    ThreadPoolTaskExecutor taskPoolExecutor;

    @Override
    public Object processForCount4(Long count) {
        for (int i = 0; i < 50; i++) {
            int index = i;
            try {
                xinTaskExecutor.execute(() -> {
                    try {
                        Thread.sleep(1000 * 90);
                        log.debug(String.valueOf(index));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            xinTaskExecutor.execute(() -> {
                try {
                    Thread.sleep(1000 * 90);
                    log.debug(String.valueOf(50));
                } catch (InterruptedException e) {
                    log.debug("this is in execute method");
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            log.debug("this is out of execute method");
            e.printStackTrace();
        }
        return "nice";
    }


    @Resource
    ThreadPoolTaskExecutor springbootPoolExecutor;

    @Override
    public Object springbootThreadPool(Long count) {
        try {
            springbootPoolExecutor.execute(() -> {
                try {
                    Thread.sleep(1000 * 1);
                    log.debug("v me 50");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "nice";
    }

    @Override
    @Async("taskPoolExecutor")
    public void processByAnnotationPool(Long count) {
        try {
            Thread.sleep(1000 * 10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("v me 50 by processByAnnotationPool");
    }


}
